package com.yunyao.framework.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunyao.common.constant.DictConstants;
import com.yunyao.common.constant.enums.AuditStatusEnums;
import com.yunyao.common.constant.enums.DataDeletedStatus;
import com.yunyao.common.constant.enums.DateFormatPattern;
import com.yunyao.common.core.BaseContext;
import com.yunyao.common.dto.payment.PaymentDto;
import com.yunyao.common.utils.DictCacheUtils;
import com.yunyao.common.web.enums.ResultMsgEnum;
import com.yunyao.common.web.util.ConvertUtil;
import com.yunyao.common.web.util.PageResult;
import com.yunyao.common.web.util.YResult;
import com.yunyao.dao.model.*;
import com.yunyao.dao.service.bamu.*;
import com.yunyao.framework.audit.PaymentAuditHandle;
import com.yunyao.framework.dto.audit.ApprovalDto;
import com.yunyao.framework.dto.audit.SubmitApprovalDto;
import com.yunyao.framework.dto.payment.PaymentNodeSaveDto;
import com.yunyao.framework.dto.payment.PaymentSaveDto;
import com.yunyao.framework.service.PaymentService;
import com.yunyao.framework.vo.payment.PaymentContractInvoiceVO;
import com.yunyao.framework.vo.payment.PaymentHistoryVO;
import com.yunyao.framework.vo.payment.PaymentNodeVO;
import com.yunyao.framework.vo.payment.PaymentVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 付款管理ServiceImpl
 *
 * @author chenyejian
 * @Date 2024/7/31 11:24
 */
@Slf4j
@Service
public class PaymentServiceImpl implements PaymentService {
    @Autowired
    private IBamuPaymentService paymentService;
    @Autowired
    private IBamuPaymentHistoryService paymentHistoryService;
    @Autowired
    private IBamuPaymentContractInvoiceService paymentContractInvoiceService;
    @Autowired
    private IBamuPaymentNodeService paymentNodeService;
    @Autowired
    private PaymentAuditHandle auditHandle;
    @Autowired
    private IBamuPurchaseContractService purchaseContractService;

    /**
     * 分页查询付款信息
     *
     * @param paymentDto 付款查询条件封装对象
     * @return 包含分页结果的YResult对象，成功时携带PageResult<PaymentVO>类型的付款信息列表
     */
    @Override
    public YResult<PageResult<PaymentVO>> pageList(PaymentDto paymentDto) {
        // 构建查询条件
        LambdaQueryWrapper<BamuPayment> wrapper = new LambdaQueryWrapper<BamuPayment>()
                .like(BamuPayment::getContractName, paymentDto.getContractName())
                .like(BamuPayment::getProjectId, paymentDto.getProjectName())
                .like(BamuPayment::getPurchaseDeptName, paymentDto.getPurchaseDeptName())
                .eq(BamuPayment::getIsDeleted, DataDeletedStatus.NO.getType())
                .orderByDesc(BamuPayment::getCreatedAt)
                .in(CollectionUtils.isNotEmpty(BaseContext.getProjectList()),
                        BamuPayment::getProjectId, BaseContext.getProjectList())
                .in(CollectionUtils.isNotEmpty(BaseContext.getSupplierList()),
                        BamuPayment::getSupplierDeptId, BaseContext.getSupplierList());
        if (com.yunyao.common.web.util.StringUtils.isNotEmpty(paymentDto.getBeginDate())) {
            wrapper.ge(BamuPayment::getReceiveDate, ConvertUtil.getString2Date(paymentDto.getBeginDate(), DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        }
        if (com.yunyao.common.web.util.StringUtils.isNotEmpty(paymentDto.getEndDate())) {
            wrapper.le(BamuPayment::getReceiveDate, ConvertUtil.getString2Date(paymentDto.getEndDate(), DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        }

        // 分页查询
        IPage<BamuPayment> payPage = new Page<>(paymentDto.getPageIndex(),
                paymentDto.getPageSize());
        payPage = paymentService.page(payPage, wrapper);

        // 处理查询结果
        if (CollectionUtils.isEmpty(payPage.getRecords())) {
            return YResult.success(new PageResult<>());
        }

        // 转换为VO对象列表
        List<PaymentVO> list = daoToVoList(payPage.getRecords());

        // 返回分页结果
        return YResult.success(new PageResult<>(list, payPage.getCurrent(), payPage.getSize(),
                payPage.getPages(), payPage.getTotal()));
    }


    /**
     * 将数据访问对象列表（DAO）转换为视图对象列表（VO）
     *
     * @param records 数据访问对象列表，包含待转换的支付记录
     * @return 视图对象列表，包含了转换后的支付信息
     */
    private List<PaymentVO> daoToVoList(List<BamuPayment> records) {
        // 使用Java 8的流式API对records进行转换，每个BamuPayment对象都映射成一个PaymentVO对象
        return records.stream().map(this::daoToVo).collect(Collectors.toList());
    }

    /**
     * 将BamuPayment实体转换为PaymentVO对象
     *
     * @param bamuPayment BamuPayment实体对象，代表数据库中支付信息的映射
     * @return PaymentVO对象，包含了转换后的支付信息，用于视图展示
     * <p>
     * 说明：本方法通过BeanUtils的copyProperties方法，将BamuPayment对象的属性复制到PaymentVO对象中，
     * 实现了从数据库实体到视图对象的转换，简化了数据处理流程。
     */
    private PaymentVO daoToVo(BamuPayment bamuPayment) {
        PaymentVO vo = new PaymentVO();
        BeanUtils.copyProperties(bamuPayment, vo);
        vo.setReceiveDate(ConvertUtil.getFormatDate(bamuPayment.getReceiveDate(), false, DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        /**
         * 收款方式字典转化
         */
        vo.setReceiveTypeName(DictCacheUtils.getDictValue("collection_methods", bamuPayment.getReceiveType()));
        return vo;
    }

    /**
     * 根据ID获取支付详情
     * <p>
     * 此方法通过调用paymentService的getById方法查询支付记录，
     * 如果查询到记录，则将记录转换为PaymentVO对象并返回；
     * 如果未查询到记录，则返回一个错误结果；
     * 如果在查询过程中发生异常，则捕获异常并返回一个错误结果
     *
     * @param id 支付记录的唯一标识
     * @return 包含支付详情的结果对象，成功时包含PaymentVO对象，失败时包含错误信息
     */
    @Override
    public YResult<PaymentVO> getDetailById(String id) {
        try {
            // 调用service层方法通过ID获取支付记录
            BamuPayment payment = paymentService.getById(id);
            if (payment == null) {
                // 如果查询结果为空，返回一个失败的结果
                return YResult.error("支付信息不存在");
            }
            // 将查询到的支付记录转换为VO对象
            PaymentVO paymentVO = daoToVo(payment);
            // 返回成功结果，携带支付信息VO对象
            return YResult.success(paymentVO);
        } catch (Exception e) {
            // 捕获并处理异常
            log.error("获取支付详情时发生异常: ", e);
            // 返回失败结果，携带错误信息
            return YResult.error("获取支付详情失败");
        }
    }


    /**
     * 根据ID删除支付记录
     * <p>
     * 此方法主要通过ID标记支付记录为已删除状态而不是物理删除它
     * 它首先检查ID是否有效，然后尝试获取对应的支付记录
     * 如果记录不存在，它会返回一个错误结果，否则它会更新记录的删除状态并返回成功结果
     *
     * @param id 支付记录的唯一标识符
     * @return YResult对象，其中包含操作结果或错误信息
     */
    @Override
    public YResult<String> deleteById(String id) {
        // 检查ID是否为空，如果为空，则返回参数错误结果
        if (StringUtils.isEmpty(id)) {
            return YResult.error(ResultMsgEnum.PARAM_ERROR);
        }
        // 通过ID获取支付记录
        BamuPayment payment = paymentService.getById(id);
        // 如果支付记录不存在，则返回无数据结果
        if (payment == null) {
            return YResult.error(ResultMsgEnum.NO_DATA);
        }
        // 将支付记录标记为已删除状态
        payment.setIsDeleted(DataDeletedStatus.YES.getType());
        // 更新支付记录
        paymentService.updateById(payment);
        // 返回删除成功结果
        return YResult.success("删除成功");
    }


    /**
     * 根据合同ID查询付款历史记录列表
     *
     * @param paymentDto 包含合同ID的查询条件对象
     * @return YResult包装的付款历史记录列表，如果没有找到记录，返回空列表
     */
    @Override
    public YResult<List<PaymentHistoryVO>> getHistoryList(PaymentDto paymentDto) {
        // 构建查询条件
        LambdaQueryWrapper<BamuPaymentHistory> wrapper =
                new LambdaQueryWrapper<BamuPaymentHistory>()
                        .eq(StringUtils.isNotEmpty(paymentDto.getContractId()),BamuPaymentHistory::getContractId, paymentDto.getContractId())
                        .eq(StringUtils.isNotEmpty(paymentDto.getReceiveId()),BamuPaymentHistory::getReceiveId, paymentDto.getReceiveId())
                        .eq(BamuPaymentHistory::getIsDeleted, DataDeletedStatus.NO.getType())
                        .orderByDesc(BamuPaymentHistory::getCreatedAt);
        // 执行查询，获取付款历史记录列表
        List<BamuPaymentHistory> paymentHistoryList = paymentHistoryService.list(wrapper);
        // 如果列表为空，返回一个空的YResult对象
        if (CollectionUtils.isEmpty(paymentHistoryList)) {
            return YResult.success(new ArrayList<>());
        }
        // 将查询结果转换为VO列表，并包装在YResult对象中返回
        return YResult.success(historyDaoToVoList(paymentHistoryList));
    }


    /**
     * 将支付历史记录DAO列表转换为视图对象列表
     * 这个方法的存在是为了将数据库中获取的支付历史记录（以BamuPaymentHistory形式）转换为
     * 更易于前端展示的格式（PaymentHistoryVO），确保前端展示的数据与后端存储的数据结构一致
     *
     * @param paymentHistoryList 数据库中查询到的支付历史记录列表
     * @return 转换后的视图对象列表，用于前端展示
     */
    private List<PaymentHistoryVO> historyDaoToVoList(List<BamuPaymentHistory> paymentHistoryList) {
        return paymentHistoryList.stream().map(this::historyDaoToVo).collect(Collectors.toList());
    }

    /**
     * 将数据库访问对象转换为视图对象
     * 该方法用于将支付历史的数据库访问对象（BamuPaymentHistory）转换为视图对象（PaymentHistoryVO）
     * 主要用于展示数据，减少前端和后端数据格式的差异，提高代码的可读性和易维护性
     *
     * @param bamuPaymentHistory 需要转换的支付历史数据库访问对象
     * @return 转换后的支付历史视图对象
     */
    private PaymentHistoryVO historyDaoToVo(BamuPaymentHistory bamuPaymentHistory) {
        PaymentHistoryVO vo = new PaymentHistoryVO();
        BeanUtils.copyProperties(bamuPaymentHistory, vo);
        return vo;
    }

    /**
     * 根据合同ID查询发票列表
     *
     * @param paymentDto 包含合同ID的参数对象
     * @return 包含发票列表的YResult对象，如果找不到相关发票，则返回空列表
     */
    @Override
    public YResult<List<PaymentContractInvoiceVO>> getInvoiceList(PaymentDto paymentDto) {
        // 构建查询条件
        List<BamuPaymentContractInvoice> invoiceList = paymentContractInvoiceService.getPaymentContractInvoiceByContractId(paymentDto.getContractId());
        return YResult.success(invoiceDaoToVoList(invoiceList));
    }

    /**
     * 根据receiveId查询发票列表
     *
     * @param paymentDto 包含合同ID的参数对象
     * @return 包含发票列表的YResult对象，如果找不到相关发票，则返回空列表
     */
    @Override
    public YResult<List<PaymentContractInvoiceVO>> getReceiveInvoiceList(PaymentDto paymentDto) {
        // 构建查询条件
        LambdaQueryWrapper<BamuPaymentContractInvoice> wrapper =
                new LambdaQueryWrapper<BamuPaymentContractInvoice>()
                        .eq(BamuPaymentContractInvoice::getReceiveId, paymentDto.getReceiveId())
                        .eq(BamuPaymentContractInvoice::getIsDeleted,
                                DataDeletedStatus.NO.getType());
        // 执行查询，获取合同发票列表
        List<BamuPaymentContractInvoice> contractInvoiceList =
                paymentContractInvoiceService.list(wrapper);
        // 如果列表为空，返回一个空的YResult对象
        if (CollectionUtils.isEmpty(contractInvoiceList)) {
            return YResult.success(new ArrayList<>());
        }
        // 将查询结果转换为VO列表，并包装在YResult对象中返回
        return YResult.success(invoiceDaoToVoList(contractInvoiceList));
    }


    /**
     * 将发票DAO列表转换为发票VO列表
     * <p>
     * 此方法接收一个PaymentContractInvoice的列表作为参数，将其转换为PaymentContractInvoiceVO的列表
     * 主要用于数据展示层，在将数据从DAO层传输到展示层时使用，以实现数据的分离和抽象
     *
     * @param contractInvoiceList 发票DAO列表，需要被转换的源数据
     * @return 返回转换后的发票VO列表
     */
    private List<PaymentContractInvoiceVO> invoiceDaoToVoList(List<BamuPaymentContractInvoice> contractInvoiceList) {
        return contractInvoiceList.stream().map(this::invoiceDaoToVo).collect(Collectors.toList());
    }

    /**
     * 将数据库访问对象（DAO）层的发票信息转换为视图对象（VO）层的发票信息
     * 此方法主要用于数据结构的转换，以便将从数据库查询到的发票数据
     * 封装成视图层所需的格式，进行展示或进一步处理
     *
     * @param bamuPaymentContractInvoice 数据库访问层的发票信息对象，包含从数据库查询到的发票数据
     * @return 返回转换后的视图层发票信息对象，该对象的数据结构更适合展示或前端操作
     */
    private PaymentContractInvoiceVO invoiceDaoToVo(BamuPaymentContractInvoice bamuPaymentContractInvoice) {
        PaymentContractInvoiceVO vo = new PaymentContractInvoiceVO();
        BeanUtils.copyProperties(bamuPaymentContractInvoice, vo);
        vo.setInvoiceDate(ConvertUtil.getString2Date(ConvertUtil.getFormatDate(bamuPaymentContractInvoice.getInvoiceDate())));
        return vo;
    }

    /**
     * 根据支付单ID查询支付节点列表
     * <p>
     * 本方法的目的是根据提供的支付单信息，查询出未被标记为删除的所有支付节点
     * 如果查询结果为空，将返回一个成功的空列表结果对象；否则，将返回包含查询结果的成功的结果对象
     *
     * @param paymentDto 包含支付单ID的参数对象，用于构建查询条件
     * @return 返回一个YResult对象，其中包含查询到的支付节点列表如果查询不到任何支付节点，列表将为空
     */
    @Override
    public YResult<List<PaymentNodeVO>> getPaymentNodeList(PaymentDto paymentDto) {
        // 构建查询条件
        LambdaQueryWrapper<BamuPaymentNode> wrapper = new LambdaQueryWrapper<BamuPaymentNode>()
                .eq(BamuPaymentNode::getReceiveId, paymentDto.getId())
                .eq(BamuPaymentNode::getIsDeleted, DataDeletedStatus.NO.getType());
        // 使用构建的查询条件执行查询操作
        List<BamuPaymentNode> paymentNodeList = paymentNodeService.list(wrapper);
        // 如果查询结果为空，返回一个成功的空列表结果对象
        if (CollectionUtils.isEmpty(paymentNodeList)) {
            return YResult.success(new ArrayList<>());
        }
        // 如果查询结果不为空，将查询结果转换为所需的视图列表，并返回一个包含查询结果的成功的结果对象
        return YResult.success(nodeDaoToVoList(paymentNodeList));
    }


    /**
     * 将支付节点实体列表转换为视图对象列表
     * <p>
     * 本函数使用Java 8的Stream API对实体列表进行转换，目的是为了数据展示或传输的需要
     * 它避开了传统循环结构，采用更简洁、更易于理解的流式操作，提高了代码的可读性和维护性
     *
     * @param paymentNodeList 支付节点实体列表，包含所有需要转换的支付节点数据
     * @return 返回转换后的支付节点视图对象列表
     */
    private List<PaymentNodeVO> nodeDaoToVoList(List<BamuPaymentNode> paymentNodeList) {
        return paymentNodeList.stream().map(this::nodeDaoToVo).collect(Collectors.toList());
    }

    /**
     * 将数据库访问对象（DAO）层的支付节点实体转换为视图对象（VO）
     *
     * @param bamuPaymentNode 数据库访问对象层的支付节点实体
     * @return 转换后的支付节点视图对象
     */
    private PaymentNodeVO nodeDaoToVo(BamuPaymentNode bamuPaymentNode) {
        PaymentNodeVO vo = new PaymentNodeVO();
        BeanUtils.copyProperties(bamuPaymentNode, vo);
        return vo;
    }

    @Override
    public YResult<String> saveOrUpdate(PaymentSaveDto dto) {
        // 检查传入的对象是否为空
        Boolean isEdit = false;
        if (Objects.isNull(dto)) {
            log.error("PaymentSaveDto is null.");
            return YResult.error(ResultMsgEnum.PARAM_ERROR);
        }
        try {
            BamuPayment payment = getBamuPayment(dto);
            if (StringUtils.isNotEmpty(payment.getId())){
                isEdit = true;
            }
            // 执行保存或更新操作，并检查是否成功
            boolean saveOrUpdate = paymentService.saveOrUpdate(payment);
            if (!saveOrUpdate) {
                log.error("Failed to save or update payment.");
                return YResult.error(ResultMsgEnum.SYS_ERROR);
            }


            String receiveId = payment.getId();
            List<PaymentNodeSaveDto> receiveNodes = dto.getReceiveNodes();
            if (CollectionUtils.isNotEmpty(receiveNodes)) {
                receiveNodes.forEach(nodeSaveDto -> {
                    nodeSaveDto.setReceiveId(receiveId);
                    nodeSaveOrUpdate(nodeSaveDto);
                });
            }

            if (!isEdit){
                String contractId = payment.getContractId();
                List<BamuPaymentContractInvoice> paymentContractInvoiceList = paymentContractInvoiceService.getPaymentContractInvoiceByContractId(contractId);
                BigDecimal receivePrice = payment.getReceivePrice();
                if (CollectionUtils.isNotEmpty(paymentContractInvoiceList)) {
                    for (BamuPaymentContractInvoice contractInvoice : paymentContractInvoiceList){
                        contractInvoice.setContractId(contractId);
                        contractInvoice.setReceiveId(payment.getId());
                        contractInvoice.setAuditStatus(ConvertUtil.null2String(AuditStatusEnums.SUBMITTED.getType()));
                        contractInvoice.setIsDeleted(DataDeletedStatus.NO.getType());
                        contractInvoice.setStatus(0);
                        /**
                         * 收款金额>发票金额，则更新为剩余金额
                         */
                        if(contractInvoice.getInvoicePrice()!=null){
                            if (receivePrice.compareTo(contractInvoice.getInvoicePrice()) >= 0) {
                                contractInvoice.setPrePrice(contractInvoice.getInvoicePrice());
                                contractInvoice.setReceivePrice(contractInvoice.getInvoicePrice());
                                contractInvoice.setNoReceivePrice(BigDecimal.ZERO);
                                /**
                                 * receivePrice-invoicePrice=剩余金额
                                 */
                                receivePrice = receivePrice.subtract(contractInvoice.getInvoicePrice());
                            }else {
                                /**
                                 * receivePrice<invoicePrice，则更新为收款金额
                                 */
                                contractInvoice.setPrePrice(receivePrice);
                                contractInvoice.setReceivePrice(receivePrice);
                                contractInvoice.setNoReceivePrice(contractInvoice.getInvoicePrice().subtract(receivePrice));
                            }
                            contractInvoice.setPrePrice(payment.getReceivePrice());
                        }
                    }
                    paymentContractInvoiceService.saveBatch(paymentContractInvoiceList);
                }
            }
            

            // 操作成功，返回支付ID
            return YResult.success(payment.getId());
        } catch (Exception e) {
            log.error("Unexpected error occurred: {}", e.getMessage(), e);
            return YResult.error(ResultMsgEnum.SYS_ERROR);
        }
    }

    /**
     * 根据支付保存DTO创建支付实体
     *
     * @param dto 支付保存DTO，包含支付相关的所有信息
     * @return 创建的BamuPayment对象，用于进一步操作或存储
     */
    private BamuPayment getBamuPayment(PaymentSaveDto dto) {
        // 创建一个新的支付实体对象
        BamuPayment payment = new BamuPayment();
        // 手动复制属性以避免安全风险
        payment.setId(dto.getId());
        payment.setContractId(dto.getContractId());
        payment.setContractNo(dto.getContractNo());
        payment.setContractName(dto.getContractName());
        payment.setProjectId(dto.getProjectId());
        payment.setProjectName(dto.getProjectName());
        payment.setContractMethod(dto.getContractMethod());
        payment.setContractTotalPrice(dto.getContractTotalPrice());
        payment.setPurchaseDeptId(dto.getPurchaseDeptId());
        payment.setPurchaseDeptName(dto.getPurchaseDeptName());
        payment.setProjectDeptId(dto.getProjectDeptId());
        payment.setProjectDeptName(dto.getProjectDeptName());
        payment.setContractPrePaymentStatus(dto.getOrderPrePaymentStatus());
        payment.setOrderPrePaymentStatus(dto.getContractPrePaymentStatus());
        payment.setContractPrePaymentRate(dto.getContractPrePaymentRate());
        payment.setContractPrePaymentPrice(dto.getContractPrePaymentPrice());
        payment.setReceivePrice(dto.getReceivePrice());
        if (dto.getReceiveNodeId() != null && dto.getReceiveNodeId().size()>0) {
            payment.setReceiveNodeId(dto.getReceiveNodeId().stream().map(String::valueOf).collect(Collectors.joining(",")));
        }
        payment.setReceiveNodeName(dto.getReceiveNodeName());
        payment.setFile(dto.getFile());
        payment.setMark(dto.getMark());
        payment.setSupplierDeptId(dto.getSupplierDeptId());
        payment.setSupplierDeptName(dto.getSupplierDeptName());
        payment.setReceiveTypeName(dto.getReceiveTypeName());
        payment.setBalanceAmount(dto.getBalanceAmount());
        payment.setRelatedReceiveType(dto.getRelatedReceiveType());
        payment.setRelatedReceiveAmount(dto.getRelatedReceiveAmount());
        payment.setRelatedReceiveId(dto.getRelatedReceiveId());
        payment.setSignDate(DateUtils.parseDate(dto.getSignDate(),
                DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        payment.setContractEndDate(DateUtils.parseDate(dto.getContractEndDate(),
                DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        payment.setReceiveDate(DateUtils.parseDate(dto.getReceiveDate(),
                DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        payment.setRelatedReceiveDate(DateUtils.parseDate(dto.getRelatedReceiveDate(),
                DateFormatPattern.YEAR_MONTH_DAY.getPattern()));

        payment.setReceivePrice(dto.getReceivePrice());
        payment.setReceiveType(dto.getReceiveType());
        try {
            payment.setReceiveTypeName(DictCacheUtils.getDictValue(DictConstants.COLLECTION_METHODS,dto.getReceiveType()));
        }catch (Exception e){
            log.error("收款类型字典数据异常",e);
        }
        payment.setFile(JSON.toJSONString(dto.getFile()));
        payment.setMark(dto.getMark());
        payment.setStatus(0);
        payment.setIsDeleted(DataDeletedStatus.NO.getType());
        BamuPurchaseContract contract = purchaseContractService.getById(dto.getContractId());
        if (Objects.nonNull(contract)) {
            payment.setContractNo(contract.getContractNo());
            payment.setContractId(contract.getId());
            payment.setContractNo(contract.getContractNo());
            payment.setContractName(contract.getContractName());
            payment.setProjectId(contract.getProjectId());
            payment.setProjectName(contract.getProjectName());
            payment.setSignDate(contract.getSignDate());
            payment.setContractMethod(contract.getContractMethod());
            payment.setContractTotalPrice(contract.getContractTotalPrice());
            payment.setPurchaseDeptId(contract.getPurchaseDeptId());
            payment.setPurchaseDeptName(contract.getPurchaseDeptName());
            payment.setProjectDeptId(contract.getProjectDeptId());
            payment.setProjectDeptName(contract.getProjectDeptName());
            payment.setContractEndDate(contract.getPaymentDeadlineDate());
            payment.setSupplierDeptId(contract.getSupplierDeptId());
            payment.setSupplierDeptName(contract.getSupplierDeptName());
        }

        return payment;
    }


    @Override
    public YResult<String> nodeSaveOrUpdate(PaymentNodeSaveDto dto) {
        // 检查传入的对象是否为空
        if (Objects.isNull(dto)) {
            log.error("PaymentNodeSaveDto is null.");
            return YResult.error(ResultMsgEnum.PARAM_ERROR);
        }
        try {
            BamuPaymentNode paymentNode = getBamuPaymentNode(dto);
            // 执行保存或更新操作，并检查是否成功
            boolean saveOrUpdate = paymentNodeService.saveOrUpdate(paymentNode);
            if (!saveOrUpdate) {
                log.error("Failed to save or update payment.");
                return YResult.error(ResultMsgEnum.SYS_ERROR);
            }
            // 操作成功，返回支付ID
            return YResult.success(dto.getId());
        } catch (Exception e) {
            log.error("Unexpected error occurred: {}", e.getMessage(), e);
            return YResult.error(ResultMsgEnum.SYS_ERROR);
        }
    }

    private BamuPaymentNode getBamuPaymentNode(PaymentNodeSaveDto dto) {
        BamuPaymentNode paymentNode = new BamuPaymentNode();
        paymentNode.setId(dto.getId());
        paymentNode.setNodeId(dto.getNodeId());
        paymentNode.setNodeName(dto.getNodeName());
        paymentNode.setReceivePrice(dto.getReceivePrice());
        paymentNode.setContractId(dto.getContractId());
        paymentNode.setReceiveId(dto.getReceiveId());
        paymentNode.setNodeType(dto.getNodeType());
        paymentNode.setNodeTriggerType(dto.getNodeTriggerType());
        paymentNode.setBackPaymentDate(DateUtils.parseDate(dto.getBackPaymentDate(),
                DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        paymentNode.setReceiveDate(DateUtils.parseDate(dto.getReceiveDate(),
                DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        return paymentNode;
    }

    @Override
    public YResult<String> invoiceConnect(PaymentDto paymentDto) {
        return null;
    }


    /**
     * 提交审批操作
     * 该方法接收一个审批数据传输对象（SaleContractSubmitApprovalDto），尝试提交销售合同的审批流程
     * 如果提交成功，返回一个成功结果，包含审批的ID；如果提交过程中发生异常，
     * 则返回一个错误结果，包含异常信息
     *
     * @param approvalDto 审批数据传输对象，包含审批所需的必要信息
     * @return YResult<String> 返回一个包含结果状态和审批ID的结果对象
     */
    @Override
    public YResult<String> submitApproval(SubmitApprovalDto approvalDto) {
        try {
            // 调用处理类的submit方法，传入审批ID，执行审批提交操作
            auditHandle.submit(approvalDto.getId());
            // 如果审批提交成功，返回成功结果，包含审批的ID
            return YResult.success(approvalDto.getId());
        } catch (Exception e) {
            // 如果审批提交过程中发生异常，返回错误结果，包含异常信息
            return YResult.error(e.getMessage());
        }
    }

    /**
     * 审批销售合同
     * 该方法接收一个销售合同审批数据传输对象，并尝试对其进行审批操作
     * 如果审批成功，返回一个表示成功的YResult对象，包含审批后的ID
     * 如果审批过程中出现异常，返回一个表示错误的YResult对象，包含错误信息
     *
     * @param approvalDto 销售合同审批Dto，包含审批所需信息
     * @return YResult对象，表示审批结果
     */
    @Override
    public YResult<String> approval(ApprovalDto approvalDto) {
        try {
            // 调用审批处理类的approval方法进行审批操作
            auditHandle.approval(approvalDto);
            // 审批成功后，返回成功结果，携带审批后的ID
            return YResult.success(approvalDto.getId());
        } catch (Exception e) {
            // 审批过程中发生异常，返回错误结果，携带异常信息
            return YResult.error(e.getMessage());
        }
    }

    @Override
    public YResult<String> revocation(ApprovalDto approvalDto) {
        return null;
    }
}
